/*
	StargateWW for GarrysMod10
	Copyright (C) 2008 Prefanatic

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

require("datastream")

WEATHER={
	["sunny"]={
		Brightness=0,
		Contrast=1,
		Colour=1,
		Precipitation=0,
		SoundLevel=3.9,
		Pitch=100,
		GoodName="Sunny"
	},
	["cloudy"]={
		Brightness=0,
		Contrast=1,
		Colour=0.6,
		Precipitation=0,
		SoundLevel=3.9,
		Pitch=100,
		GoodName="Cloudy"
	},
	["rain"]={
		Brightness=-0.07,
		Contrast=0.9,
		Colour=0.4,
		Precipitation=10,
		SoundLevel=3.9,
		Pitch=100,
		Sound="ambient/weather/rumble_rain_nowind.wav",
		GoodName="Rain"
	},
	["heavyrain"]={
		Brightness=-0.07,
		Contrast=0.9,
		Colour=0.4,
		Precipitation=15,
		SoundLevel=3.9,
		Pitch=100,
		Sound="ambient/weather/rumble_rain_nowind.wav",
		GoodName="Heavy Rain"
	},
	["sunnyrain"]={
		Brightness=0,
		Contrast=0.7,
		Colour=1.2,
		Precipitation=10,
		SoundLevel=3.9,
		Pitch=100,
		Sound="ambient/weather/rumble_rain_nowind.wav",
		GoodName="Sunny Rain"
	},
	["storm"]={
		Brightness=-0.15,
		Contrast=0.7,
		Colour=0.1,
		Precipitation=20,
		SoundLevel=3.9,
		Pitch=100,
		Sound="ambient/weather/rumble_rain.wav",
		GoodName="Storm"
	},
	["dark"]={
		Brightness=0,
		Contrast=0.3,
		Colour=1,
		Precipitation=0,
		SoundLevel=3.9,
		Pitch=100,
		GoodName="Dark"
	},
	["darkrain"]={
		Brightness=0,
		Contrast=0.3,
		Colour=1,
		Precipitation=5,
		SoundLevel=3.9,
		Pitch=100,
		Sound="ambient/weather/rumble_rain_nowind.wav",
		GoodName="Dark Rain"
	},
}

local Thunder = {
		Sound( "ambient/atmosphere/thunder4.wav" ),
		Sound( "ambient/weather/thunder3.wav"    ),
		Sound( "ambient/atmosphere/thunder1.wav" ),
		Sound( "ambient/weather/thunder4.wav"    ),
		Sound( "ambient/weather/thunder2.wav"    ),
		Sound( "ambient/weather/thunder6.wav"    ),
		Sound( "ambient/weather/thunder5.wav"    ),
		Sound( "ambient/atmosphere/thunder2.wav" ),
		Sound( "ambient/atmosphere/thunder3.wav" ),
		Sound( "ambient/weather/thunder1.wav"    )
		}
local Explosion = {
		Sound( "ambient/explosions/explode_6.wav" ),
		Sound( "ambient/explosions/explode_3.wav" ),
		Sound( "ambient/explosions/explode_1.wav" ),
		Sound( "ambient/explosions/explode_7.wav" ),
		Sound( "ambient/explosions/explode_5.wav" ),
		Sound( "ambient/explosions/explode_4.wav" ),
		Sound( "ambient/explosions/explode_2.wav" ),
		Sound( "ambient/explosions/explode_9.wav" ),
		Sound( "ambient/explosions/explode_8.wav" )
		}

local function DispEffect( name, data )
	local data2, k, v

	data2 = EffectData( )
		for k, v in pairs( data ) do
			data2[ "Set" .. k ]( data2, v )
		end
	util.Effect( name, data2 )
end

local CurWeather={
		Brightness=0,
		Contrast=1,
		Colour=1,
		SoundLevel=3.9,
		Pitch=100,
		Precipitation=0,
}

SetGlobalString("weather","sunny")

local WeatherSound=nil
local PrevWeather="sunny"
local LastLightning=0

function funcCallback_weathermod_enabled(CVar, PreviousValue, NewValue)
	if WeatherSound then WeatherSound:Stop() end
	if NewValue == 1 then
		local WeatherName=GetGlobalString("weather")
		if WEATHER[WeatherName].Sound then
			WeatherSound=CreateSound(LocalPlayer(),WEATHER[WeatherName].Sound)
			WeatherSound:Play()
			PrevWeather=WeatherName
		else
			WeatherSound=nil
		end
	end
end
cvars.AddChangeCallback("weathermod_enabled", funcCallback_weathermod_enabled) 

function WeatherOverlay()
	if ( GetConVar("weathermod_enabled"):GetBool() == false) then return end
	if render.GetDXLevel() < 80 then return end

	local WeatherName=GetGlobalString("weather")
	
	if not WeatherName or not WEATHER[WeatherName] then WeatherName="sunny" end
	
	local traced = {}
	traced.start = LocalPlayer():GetPos()
	traced.endpos = LocalPlayer():GetPos()+Vector(0,0,700)
	traced.mask = MASK_NPCWORLDSTATIC
	local tr=util.TraceLine(traced)
	
	if tr.HitWorld then
		CurWeather.Brightness=math.Approach( CurWeather.Brightness, math.Clamp(WEATHER[WeatherName].Brightness,0,5), 0.001 )
		CurWeather.Contrast=math.Approach( CurWeather.Contrast, math.Clamp(WEATHER[WeatherName].Contrast,1,5), 0.001 )
		CurWeather.Colour=math.Approach( CurWeather.Colour, math.Clamp(WEATHER[WeatherName].Colour,1,5), 0.001 )
	else
	
		CurWeather.Brightness=math.Approach( CurWeather.Brightness, WEATHER[WeatherName].Brightness, 0.001 )
		CurWeather.Contrast=math.Approach( CurWeather.Contrast, WEATHER[WeatherName].Contrast, 0.001 )
		CurWeather.Colour=math.Approach( CurWeather.Colour, WEATHER[WeatherName].Colour, 0.001 )
	
	end
	CurWeather.Precipitation=math.Approach( CurWeather.Precipitation, math.Clamp(WEATHER[WeatherName].Precipitation,0,25), 0.01 )
	

	local ScrColTab = {}
	ScrColTab[ "$pp_colour_addr" ] 		= 0
	ScrColTab[ "$pp_colour_addg" ] 		= 0
	ScrColTab[ "$pp_colour_addb" ] 		= 0
	ScrColTab[ "$pp_colour_brightness" ]= CurWeather.Brightness
	ScrColTab[ "$pp_colour_contrast" ] 	= CurWeather.Contrast
	ScrColTab[ "$pp_colour_colour" ] 	= CurWeather.Colour
	ScrColTab[ "$pp_colour_mulr" ] 		= 0
	ScrColTab[ "$pp_colour_mulg" ] 		= 0
	ScrColTab[ "$pp_colour_mulb" ] 		= 0
	DrawColorModify(ScrColTab)
	
	if not PrevWeather or PrevWeather~=WeatherName then
		if WeatherSound then WeatherSound:Stop() end
		if WEATHER[WeatherName].Sound then
			WeatherSound=CreateSound(LocalPlayer(),WEATHER[WeatherName].Sound)
			WeatherSound:Play()
			PrevWeather=WeatherName
		else
			WeatherSound=nil
		end
	end
	
	if CurTime()>LastLightning and CurWeather.Precipitation>10 then
		if math.random(1,20)==10 then
			LastLightning=CurTime()+30
			CurWeather.Contrast=5
			timer.Simple(0.2,function()
				CurWeather.Contrast=WEATHER[WeatherName].Contrast
			end)
			timer.Simple(3,function()
				--surface.PlaySound(table.Random( Thunder ))
				surface.PlaySound(Format("ambient/atmosphere/thunder%i.wav",math.random(1,4)))  
			end)
		end
	end
	
	if WeatherSound and tr.HitWorld or (WeatherSound and LocalPlayer():InVehicle()) then
		CurWeather.SoundLevel=math.Approach( CurWeather.SoundLevel, 2, 0.195 )
		CurWeather.Pitch=math.Approach( CurWeather.Pitch, 50, 2 )
		WeatherSound:SetSoundLevel(CurWeather.SoundLevel)
		WeatherSound:ChangePitch(CurWeather.Pitch)
	elseif WeatherSound then
		CurWeather.SoundLevel=math.Approach( CurWeather.SoundLevel, 3.9, 0.195 )
		CurWeather.Pitch=math.Approach( CurWeather.Pitch, 100, 2 )
		WeatherSound:SetSoundLevel(CurWeather.SoundLevel)
		WeatherSound:ChangePitch(CurWeather.Pitch)
	end

end
hook.Add("RenderScreenspaceEffects", "WeatherOverlay", WeatherOverlay)

local LastEffect=0
function WeatherThink()
	if ( GetConVar("weathermod_enabled"):GetBool() == false) then return end
	local WeatherName=GetGlobalString("weather")
	if not WeatherName or not WEATHER[WeatherName] then WeatherName="sunny" end
	if CurWeather.Precipitation>0 then
		if CurTime()>LastEffect then
			LastEffect=CurTime()+math.random(0.8,1)
			local eff=EffectData()
				eff:SetMagnitude(CurWeather.Precipitation)
			util.Effect("rain",eff)
		end
	end
end
hook.Add("Think","",WeatherThink)

function RcvLightningEntity( handler, id, rawdata, ent ) 
	CurWeather.Contrast=5
	timer.Simple(0.2,function()
		CurWeather.Contrast=WEATHER[GetGlobalString("weather")].Contrast
	end)
	if not ent:IsValid() then return end
	LastLightning=CurTime()+math.random(10,40)
--	surface.PlaySound(table.Random( Explosion ))
	local res, start, ende
--	start = ent:LocalToWorld(ent:OBBCenter()) + Vector(0,0,1000)
	--ende = start + self.Distance * self.Owner:GetAimVector( )
	
	start = ent:LocalToWorld(ent:OBBCenter()) + Vector(0,0,1000)
	ende = ent:LocalToWorld(ent:OBBCenter())

	res = util.TraceLine{ start = start, endpos = ende, filter = ent, mask = MASK_SHOT }
	
	--DispEffect( "bolt", { Origin = start, Normal = res.HitNormal, Start = ende, Scale = 240, Radius = 12 } )
	
	local effectdata = EffectData()
	effectdata:SetOrigin( ent:LocalToWorld(ent:OBBCenter()) + Vector(0,0,10000) )
	effectdata:SetStart( ent:LocalToWorld(ent:OBBCenter()) )
	effectdata:SetAttachment( 1 )
	effectdata:SetEntity( ent )
	util.Effect( "ToolTracer", effectdata )
	
	DispEffect( "ThumperDust", { Origin = res.HitPos, Start = res.HitPos, Normal = res.HitNormal, Scale = 500, Radius = 45, Angle = res.HitNormal:Angle( ) } )
	surface.PlaySound(table.Random( Thunder ))
	surface.PlaySound(table.Random( Explosion ))
 end 
 
 datastream.Hook( "LightningEntity", RcvLightningEntity ); 
 
 -- lua_run SetGlobalString("weather","storm"); showmethelightning
 
local function Menu( panel )
	panel:Help( "If the sound stuffs up, just go to another weather then back to the one you want." )
	panel:Help( "" )
	panel:CheckBox( "Enabled", "weathermod_enabled" )
	panel:Help( "" )
	panel:Help( "Weathers:" )
	for key, val in pairs( WEATHER ) do 
 		panel:Button( WEATHER[key].GoodName, "weathermod_selectweather", key ) 
 	end 
	panel:Help( "" )
	panel:CheckBox( "Lightning Enabled", "weathermod_lightning" )
	panel:Help( "" )
	panel:CheckBox( "Wind Enabled", "weathermod_wind" )
	panel:Help( "" )
	panel:Help( "Credits to Catdaemon for initial script, Kill coDer did everything else :P" )
end
local function PopulateToolMenu()
	spawnmenu.AddToolMenuOption( "Options", "Weather", "Weather Mod", "Weather Mod", "", "", Menu )
end
hook.Add( "PopulateToolMenu", "WeatherMod", PopulateToolMenu )
